﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;



/// <summary>
/// 外围一层步兵包围的方阵，锚点位于方阵中央，锚点周围等角排列着炮兵
/// id从外围顺时针开始，外围结束后，顺时针计数锚点周围的炮兵
/// </summary>

namespace Formation
{



    public class SquareSphereFormation : FormationBase
    {
        float Interval;


        public SquareSphereFormation(float Interval,float arriveDistance)
        {
            this.ArriveDistance = arriveDistance;
            this.Interval = Interval;
        }


        public override float FormationDistance(FormationUnit unit, FormationSlot slot)
        {
            float dis = 0;
            dis += unit.unit.transform.position.SqrDistance(slot.position);
            if (unit.tag == "cannon" && slot.tag == "inner")
            {
                dis *= 0.01f;
            }
            if (unit.tag == "inf" && slot.tag == "outer")
            {
                dis *= 0.01f;
            }
            return dis;
        }

        public override List<FormationSlot> GenerateSlotList(Transform pivot, List<FormationUnit> units)
        {
            List<FormationSlot> slots = new List<FormationSlot>();
            int infCount = 0;
            int cannonCount = 0;
            for (int i = 0; i < units.Count; i++)
            {
                if (units[i].tag == "inf") infCount++;
                if (units[i].tag == "cannon") cannonCount++;
            }

            for (int i = 0; i < infCount; i++)
            {
                FormationSlot slot = new FormationSlot(GetSlotPos(pivot, i, "outer", cannonCount, infCount), pivot.transform.rotation, i);
                slot.tag = "outer";
                slots.Add(slot);
            }
            for (int i = infCount; i < infCount + cannonCount; i++)
            {
                var q = GetInnerRotation(pivot, i, cannonCount, infCount);

                FormationSlot slot = new FormationSlot(GetSlotPos(pivot, i, "inner", cannonCount, infCount), GetInnerRotation(pivot, i, cannonCount, infCount), i);
                slot.tag = "inner";
                slots.Add(slot);
            }

            return slots;


        }

        private Vector3 GetSlotPos(Transform pivot, int id, string tag, int innerCount, int outerCount)
        {
            int squareLength = (outerCount + 3) / 4;
            Vector3 planePos;
            if (tag == "outer")
            {
                Vector3[] _4dir = new Vector3[4] { pivot.transform.right, -pivot.transform.forward, -pivot.transform.right, pivot.transform.forward };
                Vector3 dV = new Vector3();
                for (int i = 0; i < id; i++) dV += _4dir[i / squareLength] * Interval;
                Vector3 startPos = pivot.transform.position + (squareLength / 2.0f * Interval) * pivot.transform.forward - (squareLength / 2.0f * Interval) * pivot.transform.right;
                planePos= startPos + dV;
            }
            else if (tag == "inner")
            {
                float Deltaangle = (id - outerCount) * (360.0f / innerCount);
                planePos= pivot.transform.position + Interval * 0.2f * squareLength * Vector3.Normalize(Quaternion.AngleAxis(Deltaangle, pivot.transform.up) * pivot.transform.forward);
            }
            else
            {
                return new Vector3();
            }
            return planePos;

        }
        private Quaternion GetInnerRotation(Transform pivot, int id, int innerCount, int outerCount)
        {
            float Deltaangle = (id - outerCount) * (360.0f / innerCount);
            return Quaternion.AngleAxis(Deltaangle, pivot.transform.up) * pivot.transform.rotation;
        }

        public override void UpdateLineFormationSlotPosAndRot(Transform pivot)
        {
            int innerCount = 0;
            int outerCount = 0;
            var curSlotList = slotList;
            for (int i = 0; i < slotCount; i++)
            {
                if (curSlotList[i].tag == "inner") innerCount++;
                if (curSlotList[i].tag == "outer") outerCount++;
            }
            foreach (var fu in unitSlotList)
            {
                if (fu.Value==null) continue;
                Vector3 newPos = GetSlotPos(pivot, fu.Key.id, fu.Key.tag, innerCount, outerCount);
                fu.Key.position = newPos;
                if (fu.Key.tag == "outer") fu.Key.rotation = pivot.transform.rotation;
                else if (fu.Key.tag == "inner") fu.Key.rotation = GetInnerRotation(pivot, fu.Key.id, innerCount, outerCount);

                fu.Value.unit.desireTarget = fu.Key.position;
                
            }
        }
    }
}
